<?php

require_once 'vendor/autoload.php';

use Smalot\Cups\Builder\Builder;
use Smalot\Cups\Manager\JobManager;
use Smalot\Cups\Manager\PrinterManager;
use Smalot\Cups\Model\Job;
use Smalot\Cups\Transport\ImprovedClient;
use Smalot\Cups\Transport\ResponseParser;

/**
 * Host Header 问题修复示例
 * 
 * 这个脚本演示如何使用 ImprovedClient 类来解决
 * "Remote is not defined and we cannot determine a connection endpoint for this request (no Host header)"
 * 错误
 */
class HostHeaderFixExample
{
    private string $printerIp;
    private int $printerPort;
    private ImprovedClient $client;
    private Builder $builder;
    private ResponseParser $responseParser;

    public function __construct(string $printerIp = '10.1.0.12', int $printerPort = 631)
    {
        $this->printerIp = $printerIp;
        $this->printerPort = $printerPort;
        $this->builder = new Builder();
        $this->responseParser = new ResponseParser();
        
        echo "🔧 Host Header 问题修复示例\n";
        echo "目标打印机: {$this->printerIp}:{$this->printerPort}\n";
        echo str_repeat('=', 60) . "\n\n";
    }

    /**
     * 演示问题：使用标准客户端（会出现Host header错误）
     */
    public function demonstrateProblem(): void
    {
        echo "❌ 演示问题：使用标准客户端\n";
        echo str_repeat('-', 40) . "\n";
        
        try {
            // 使用标准客户端（可能会出现Host header问题）
            $httpClient = new \Http\Client\Socket\Client();
            $jobManager = new JobManager($this->builder, $httpClient, $this->responseParser);
            $printerManager = new PrinterManager($this->builder, $httpClient, $this->responseParser);
            
            $printerUri = "ipp://{$this->printerIp}:{$this->printerPort}/ipp/print";
            $printer = $printerManager->findByUri($printerUri);
            
            if ($printer) {
                echo "✅ 标准客户端工作正常\n";
            } else {
                echo "❌ 标准客户端无法找到打印机\n";
            }
            
        } catch (Exception $e) {
            echo "❌ 标准客户端错误: {$e->getMessage()}\n";
            
            if (strpos($e->getMessage(), 'Host header') !== false) {
                echo "   这就是我们要解决的Host header问题！\n";
            }
        }
        
        echo "\n";
    }

    /**
     * 解决方案1：使用 ImprovedClient
     */
    public function solutionImprovedClient(): bool
    {
        echo "✅ 解决方案1：使用 ImprovedClient\n";
        echo str_repeat('-', 40) . "\n";
        
        try {
            // 创建改进的客户端
            $this->client = ImprovedClient::createForIpAddress(
                $this->printerIp,
                $this->printerPort
            );
            
            echo "📋 连接信息:\n";
            $connectionInfo = $this->client->getConnectionInfo();
            foreach ($connectionInfo as $key => $value) {
                echo "   {$key}: " . (is_bool($value) ? ($value ? 'true' : 'false') : $value) . "\n";
            }
            
            // 测试连接
            echo "\n🔍 测试网络连接: ";
            if ($this->client->testConnection()) {
                echo "✅ 成功\n";
            } else {
                echo "❌ 失败\n";
                return false;
            }
            
            // 创建管理器
            $jobManager = new JobManager($this->builder, $this->client, $this->responseParser);
            $printerManager = new PrinterManager($this->builder, $this->client, $this->responseParser);
            
            // 查找打印机
            echo "🖨️  查找打印机: ";
            $printerUri = "ipp://{$this->printerIp}:{$this->printerPort}/ipp/print";
            $printer = $printerManager->findByUri($printerUri);
            
            if ($printer) {
                echo "✅ 找到打印机\n";
                echo "   名称: {$printer->getName()}\n";
                echo "   URI: {$printer->getUri()}\n";
                
                // 创建并发送测试任务
                return $this->sendTestJob($jobManager, $printer);
            } else {
                echo "❌ 未找到打印机\n";
                return false;
            }
            
        } catch (Exception $e) {
            echo "❌ ImprovedClient 错误: {$e->getMessage()}\n";
            return false;
        }
    }

    /**
     * 解决方案2：手动设置Host header
     */
    public function solutionManualHostHeader(): bool
    {
        echo "\n✅ 解决方案2：手动设置Host header\n";
        echo str_repeat('-', 40) . "\n";
        
        try {
            // 创建自定义HTTP客户端
            $customClient = new class($this->printerIp, $this->printerPort) extends \Http\Client\Socket\Client {
                private string $targetIp;
                private int $targetPort;
                
                public function __construct(string $ip, int $port)
                {
                    parent::__construct();
                    $this->targetIp = $ip;
                    $this->targetPort = $port;
                }
                
                public function sendRequest(\Psr\Http\Message\RequestInterface $request): \Psr\Http\Message\ResponseInterface
                {
                    // 手动设置Host header和其他必要的headers
                    $request = $request
                        ->withHeader('Host', $this->targetIp . ':' . $this->targetPort)
                        ->withHeader('User-Agent', 'CUPS-IPP-Client/2.0')
                        ->withHeader('Accept', 'application/ipp')
                        ->withHeader('Content-Type', 'application/ipp');
                    
                    // 修改URI
                    $uri = $request->getUri()
                        ->withHost($this->targetIp)
                        ->withPort($this->targetPort)
                        ->withScheme('http');
                    
                    $request = $request->withUri($uri);
                    
                    return parent::sendRequest($request);
                }
            };
            
            // 使用自定义客户端创建管理器
            $jobManager = new JobManager($this->builder, $customClient, $this->responseParser);
            $printerManager = new PrinterManager($this->builder, $customClient, $this->responseParser);
            
            echo "🖨️  查找打印机: ";
            $printerUri = "ipp://{$this->printerIp}:{$this->printerPort}/ipp/print";
            $printer = $printerManager->findByUri($printerUri);
            
            if ($printer) {
                echo "✅ 找到打印机\n";
                return $this->sendTestJob($jobManager, $printer);
            } else {
                echo "❌ 未找到打印机\n";
                return false;
            }
            
        } catch (Exception $e) {
            echo "❌ 手动Host header 错误: {$e->getMessage()}\n";
            return false;
        }
    }

    /**
     * 解决方案3：Windows系统打印备用方案
     */
    public function solutionWindowsFallback(): bool
    {
        echo "\n✅ 解决方案3：Windows系统打印备用方案\n";
        echo str_repeat('-', 40) . "\n";
        
        if (PHP_OS_FAMILY !== 'Windows') {
            echo "❌ 当前系统不是Windows，跳过此方案\n";
            return false;
        }
        
        $testContent = $this->createTestContent();
        $tempFile = tempnam(sys_get_temp_dir(), 'host_header_fix_');
        file_put_contents($tempFile, $testContent);
        
        $printerNames = [
            'EPSON L4260 Series',
            'EPSON L4260',
            'L4260 Series'
        ];
        
        foreach ($printerNames as $printerName) {
            echo "🖨️  尝试打印机: {$printerName} ";
            
            $command = "print /D:\"{$printerName}\" \"{$tempFile}\"";
            $output = [];
            $returnCode = 0;
            exec($command . ' 2>&1', $output, $returnCode);
            
            if ($returnCode === 0) {
                echo "✅ 成功\n";
                unlink($tempFile);
                return true;
            } else {
                echo "❌ 失败\n";
            }
        }
        
        unlink($tempFile);
        echo "❌ 所有Windows打印机名称都失败\n";
        return false;
    }

    /**
     * 发送测试打印任务
     */
    private function sendTestJob(JobManager $jobManager, $printer): bool
    {
        echo "📄 创建测试任务: ";
        
        try {
            $job = new Job();
            $job->setName('Host Header Fix Test');
            $job->setUsername('testuser');
            $job->addText($this->createTestContent());
            
            echo "✅ 创建成功\n";
            echo "📤 发送打印任务: ";
            
            $result = $jobManager->send($printer, $job);
            
            if ($result) {
                echo "✅ 发送成功\n";
                echo "   任务ID: {$job->getId()}\n";
                echo "   任务名称: {$job->getName()}\n";
                return true;
            } else {
                echo "❌ 发送失败\n";
                return false;
            }
            
        } catch (Exception $e) {
            echo "❌ 任务错误: {$e->getMessage()}\n";
            return false;
        }
    }

    /**
     * 创建测试内容
     */
    private function createTestContent(): string
    {
        $content = "";
        $content .= str_repeat('=', 50) . "\n";
        $content .= "    Host Header 问题修复测试\n";
        $content .= "      EPSON L4260 Series\n";
        $content .= str_repeat('=', 50) . "\n\n";
        
        $content .= "连接信息:\n";
        $content .= "- IP地址: {$this->printerIp}\n";
        $content .= "- 端口: {$this->printerPort}\n";
        $content .= "- 协议: IPP (Internet Printing Protocol)\n";
        $content .= "- 时间: " . date('Y-m-d H:i:s') . "\n";
        $content .= "- PHP版本: " . PHP_VERSION . "\n\n";
        
        $content .= "问题描述:\n";
        $content .= "❌ Remote is not defined and we cannot determine\n";
        $content .= "   a connection endpoint for this request (no Host header)\n\n";
        
        $content .= "解决方案:\n";
        $content .= "✅ 使用 ImprovedClient 类\n";
        $content .= "✅ 手动设置 Host header\n";
        $content .= "✅ Windows 系统打印备用方案\n\n";
        
        $content .= "技术改进:\n";
        $content .= "✓ 修复了Host header问题\n";
        $content .= "✓ 增强了错误处理\n";
        $content .= "✓ 提供了多种备用方案\n";
        $content .= "✓ 改进了网络连接检测\n\n";
        
        $content .= "如果您能看到这个测试页面，\n";
        $content .= "说明Host header问题已经解决！\n\n";
        
        $content .= str_repeat('-', 50) . "\n";
        $content .= "测试完成: " . date('Y-m-d H:i:s') . "\n";
        $content .= "修复版本: HostHeaderFix v1.0\n";
        
        return $content;
    }

    /**
     * 运行完整的修复测试
     */
    public function runFullTest(): void
    {
        // 1. 演示问题
        $this->demonstrateProblem();
        
        // 2. 尝试解决方案1：ImprovedClient
        if ($this->solutionImprovedClient()) {
            echo "\n🎉 解决方案1成功！Host header问题已修复。\n";
            return;
        }
        
        // 3. 尝试解决方案2：手动Host header
        if ($this->solutionManualHostHeader()) {
            echo "\n🎉 解决方案2成功！Host header问题已修复。\n";
            return;
        }
        
        // 4. 尝试解决方案3：Windows备用方案
        if ($this->solutionWindowsFallback()) {
            echo "\n🎉 解决方案3成功！使用Windows系统打印。\n";
            return;
        }
        
        echo "\n❌ 所有解决方案都失败了。请检查：\n";
        echo "   1. 网络连接是否正常\n";
        echo "   2. 打印机IP地址是否正确\n";
        echo "   3. 打印机IPP服务是否启用\n";
        echo "   4. 防火墙是否阻止了631端口\n";
        echo "\n📖 详细故障排除请参考: NETWORK_TROUBLESHOOTING.md\n";
    }

    /**
     * 网络诊断
     */
    public function runNetworkDiagnostics(): void
    {
        echo "\n🔍 网络诊断\n";
        echo str_repeat('-', 30) . "\n";
        
        // Ping测试
        echo "1. Ping测试: ";
        $pingCommand = PHP_OS_FAMILY === 'Windows' 
            ? "ping -n 1 -w 1000 {$this->printerIp}" 
            : "ping -c 1 -W 1 {$this->printerIp}";
        
        $output = [];
        $returnCode = 0;
        exec($pingCommand . ' 2>&1', $output, $returnCode);
        
        if ($returnCode === 0) {
            echo "✅ 成功\n";
        } else {
            echo "❌ 失败\n";
        }
        
        // 端口测试
        echo "2. 端口631测试: ";
        $connection = @fsockopen($this->printerIp, $this->printerPort, $errno, $errstr, 5);
        
        if ($connection) {
            echo "✅ 开放\n";
            fclose($connection);
        } else {
            echo "❌ 关闭 (错误: {$errno} - {$errstr})\n";
        }
        
        // HTTP测试
        echo "3. HTTP服务测试: ";
        $context = stream_context_create([
            'http' => [
                'method' => 'GET',
                'timeout' => 10,
                'header' => "Host: {$this->printerIp}:{$this->printerPort}\r\n"
            ]
        ]);
        
        $result = @file_get_contents("http://{$this->printerIp}:{$this->printerPort}/", false, $context);
        
        if ($result !== false) {
            echo "✅ 可访问\n";
        } else {
            echo "❌ 不可访问\n";
        }
        
        echo "\n";
    }
}

// 使用示例
if (basename(__FILE__) === basename($_SERVER['SCRIPT_NAME'])) {
    // 可以通过命令行参数指定打印机IP
    $printerIp = $argv[1] ?? '10.1.0.12';
    $printerPort = isset($argv[2]) ? (int)$argv[2] : 631;
    
    $example = new HostHeaderFixExample($printerIp, $printerPort);
    
    // 运行网络诊断
    $example->runNetworkDiagnostics();
    
    // 运行完整测试
    $example->runFullTest();
    
    echo "\n📚 更多信息:\n";
    echo "   - 网络故障排除: NETWORK_TROUBLESHOOTING.md\n";
    echo "   - 代码质量改进: CODE_QUALITY_IMPROVEMENTS.md\n";
    echo "   - PDF测试指南: PDF_TEST_GUIDE.md\n";
}